﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Pixysoft.Framework.Configurations.Core
{
    class HtmlDivCollection : IHtmlDivCollection
    {
        int index = -1;

        int nestlevel = 0;

        List<IHtmlDiv> divs;

        public HtmlDivCollection(IHtmlNodesCollection nodes, string path, int nestlevel)
        {
            divs = new List<IHtmlDiv>();

            this.nestlevel = nestlevel;

            foreach (IHtmlNode node in nodes)
            {
                if (string.Equals(node.ElementName, "div", StringComparison.OrdinalIgnoreCase))
                {
                    divs.Add(new HtmlDiv(node, path, nestlevel, divs.Count));
                }
                else
                {
                    SearchDiv(node, divs, path, nestlevel, null);
                }
            }
        }

        public HtmlDivCollection(IHtmlNodesCollection nodes, string path, int nestlevel, string preText)
        {
            divs = new List<IHtmlDiv>();

            this.nestlevel = nestlevel;

            foreach (IHtmlNode node in nodes)
            {
                if (string.Equals(node.ElementName, "div", StringComparison.OrdinalIgnoreCase))
                {
                    divs.Add(new HtmlDiv(node, path, nestlevel, divs.Count, preText));
                }
                else
                {
                    SearchDiv(node, divs, path, nestlevel, preText);
                }
            }
        }

        private void SearchDiv(IHtmlNode node, List<IHtmlDiv> divs, string path, int nestlevel, string preText)
        {
            foreach (IHtmlNode subnode in node.Nodes)
            {
                if (string.Equals(subnode.ElementName, "div", StringComparison.OrdinalIgnoreCase))
                {
                    IHtmlDiv subdiv = new HtmlDiv(subnode, path, nestlevel, divs.Count, preText);
                    divs.Add(subdiv);
                }
                else
                {
                    SearchDiv(subnode, divs, path, nestlevel, preText);
                }
            }
        }

        public HtmlDivCollection(List<IHtmlDiv> divs, int nestlevel)
        {
            this.nestlevel = nestlevel;
            this.divs = divs;
        }



        public IHtmlDiv this[int index]
        {
            get
            {
                return divs[index];
            }
        }

        public int Count
        {
            get { return divs.Count; }
        }

        public IHtmlDiv Search(string path)
        {
            // /1/2/3/4/5

            if (string.IsNullOrEmpty(path))
                return null;

            string[] paths = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);

            string currentpath = paths[nestlevel];

            if (nestlevel > paths.Length - 1)
                throw new Exception("path format error.");

            IHtmlDiv currentdiv = GetCurrentDiv(currentpath);

            if (nestlevel < paths.Length - 1)
                return currentdiv.Divs.Search(path);

            return currentdiv;
        }

        public IHtmlDiv[] SearchByClass(string classid)
        {
            List<IHtmlDiv> list = new List<IHtmlDiv>();

            foreach (IHtmlDiv div in divs)
            {
                if (string.Equals(classid, div.Divclass, StringComparison.OrdinalIgnoreCase))
                    list.Add(div);
                else
                    SearchByClass(div, list, classid);
            }

            return list.ToArray();
        }

        private void SearchByClass(IHtmlDiv div, List<IHtmlDiv> list, string classid)
        {
            foreach (IHtmlDiv subdiv in div.Divs)
            {
                if (string.Equals(classid, subdiv.Divclass, StringComparison.OrdinalIgnoreCase))
                {
                    list.Add(subdiv);
                }
                else
                {
                    SearchByClass(subdiv, list, classid);
                }
            }
        }

        public IHtmlDiv[] SearchById(string id)
        {
            List<IHtmlDiv> list = new List<IHtmlDiv>();

            foreach (IHtmlDiv div in divs)
            {
                if (string.Equals(id, div.Divid, StringComparison.OrdinalIgnoreCase))
                    list.Add(div);
                else
                    SearchById(div, list, id);
            }

            return list.ToArray();
        }

        private void SearchById(IHtmlDiv div, List<IHtmlDiv> list, string id)
        {
            foreach (IHtmlDiv subdiv in div.Divs)
            {
                if (string.Equals(id, subdiv.Divid, StringComparison.OrdinalIgnoreCase))
                {
                    list.Add(subdiv);
                }
                else
                {
                    SearchById(subdiv, list, id);
                }
            }
        }

        private IHtmlDiv GetCurrentDiv(string currentpath)
        {
            if (string.IsNullOrEmpty(currentpath))
                return null;

            int divindex = 0;

            if (!int.TryParse(currentpath, out divindex))
                throw new Exception("path format error.");

            if (divindex > divs.Count - 1)
                throw new Exception("path table format error.");

            IHtmlDiv div = divs[divindex];

            return div;
        }

        public string Serialize()
        {
            StringBuilder builder = new StringBuilder();
            foreach (IHtmlDiv div in divs)
            {
                builder.Append(div.Serialize());
            }
            return builder.ToString();
        }

        #region IEnumerable<IHtmlDiv> 成员

        public IEnumerator<IHtmlDiv> GetEnumerator()
        {
            return this;
        }

        #endregion

        #region IEnumerable 成员

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this;
        }

        #endregion

        #region IEnumerator<IHtmlDiv> 成员

        public IHtmlDiv Current
        {
            get
            {
                return this[index];
            }
        }

        #endregion

        #region IDisposable 成员

        public void Dispose()
        {
            Reset();
        }

        #endregion

        #region IEnumerator 成员

        object System.Collections.IEnumerator.Current
        {
            get { return this[index]; }
        }

        public bool MoveNext()
        {
            if (index >= divs.Count - 1)
                return false;

            index++;

            return true;
        }

        public void Reset()
        {
            index = -1;
        }

        #endregion

    }
}
